import "@typespec/http";
import "@typespec/versioning";

using TypeSpec.Http;
using TypeSpec.Versioning;

@service({
  title: "Pet Store",
})
@server("http://localhost:3000", "Конечная точка с одним сервером")
@versioned(Versions)
namespace PetStore;

enum Versions {
  v1: "1.0",
  v2: "2.0",
}

model Pet {
  id: int32;

  @minLength(1)
  name: string;

  @minValue(0)
  @maxValue(100)
  age: int32;

  kind: petType;
}

enum petType {
  dog: "dog",
  cat: "cat",
  fish: "fish",
  bird: "bird",
  reptile: "reptile",
}

@added(Versions.v2)
model Toy {
  id: int32;
  name: string;
}

model CommonParameters {
  @header
  requestID: string;

  @query
  locale?: string;

  @header
  clientVersion?: string;
}

model PetListResponse {
  ...OkResponse;
  ...Body<Pet[]>;
}

model PetResponse {
  ...OkResponse;
  ...Body<Pet>;
}

model PetCreatedResponse {
  ...CreatedResponse;
  ...Body<Pet>;
}

model PetAcceptedResponse {
  ...AcceptedResponse;
  ...Body<Pet>;
}

model PetErrorResponse {
  ...BadRequestResponse;
  ...Body<ValidationError>;
}

model PetNotFoundResponse {
  ...NotFoundResponse;
  ...Body<NotFoundError>;
}

model PetUnauthorizedResponse {
  ...UnauthorizedResponse;
  ...Body<UnauthorizedError>;
}

model PetSuccessResponse {
  ...OkResponse;
  ...Body<string>;
}

model PetNoContentResponse {
  ...NoContentResponse;
}

@route("/pets")
namespace Pets {
  @get
  op listPets(...CommonParameters): PetListResponse;

  @get
  op getPet(
    @path petId: int32,
    @header ifMatch?: string,
  ): PetResponse | PetNotFoundResponse;

  @post
  @useAuth(BearerAuth)
  op createPet(@body pet: Pet):
    | PetCreatedResponse
    | PetAcceptedResponse
    | PetErrorResponse
    | PetUnauthorizedResponse;

  @put
  @useAuth(BearerAuth)
  op updatePet(@path petId: int32, @body pet: Pet):
    | PetResponse
    | PetErrorResponse
    | PetUnauthorizedResponse
    | PetNotFoundResponse
    | InternalServerErrorResponse;

  @delete
  @useAuth(BearerAuth)
  op deletePet(
    @path petId: int32,
  ): PetNoContentResponse | PetUnauthorizedResponse;

  @route("{petId}/toys")
  namespace Toys {
    @added(Versions.v2)
    @get
    op listToys(@path petId: int32, ...CommonParameters): {
      @statusCode statusCode: 200;
      @body toys: Toy[];
    } | {
      @statusCode statusCode: 404;
      @body error: NotFoundError;
    };

    @added(Versions.v2)
    @post
    @useAuth(BearerAuth)
    op createToy(@path petId: int32, @body toy: Toy, ...CommonParameters): {
      @statusCode statusCode: 201;
      @body newToy: Toy;
    } | {
      @statusCode statusCode: 400;
      @body error: ValidationError;
    } | {
      @statusCode statusCode: 401;
      @body error: UnauthorizedError;
    };

    @added(Versions.v2)
    @put
    @useAuth(BearerAuth)
    op updateToy(
      @path petId: int32,
      @path toyId: int32,
      @body toy: Toy,
      ...CommonParameters,
    ):
      | {
          @body updatedToy: Toy;
        }
      | {
          @statusCode statusCode: 400;
          @body error: ValidationError;
        }
      | {
          @statusCode statusCode: 401;
          @body error: UnauthorizedError;
        }
      | {
          @statusCode statusCode: 404;
          @body error: NotFoundError;
        };

    @added(Versions.v2)
    @delete
    @useAuth(BearerAuth)
    op deleteToy(@path petId: int32, @path toyId: int32, ...CommonParameters): {
      @statusCode statusCode: 204;
    } | {
      @statusCode statusCode: 401;
      @body error: UnauthorizedError;
    };
  }
}

@error
model NotFoundError {
  code: "NOT_FOUND";
  message: string;
}

@error
model ValidationError {
  code: "VALIDATION_ERROR";
  message: string;
  details: string[];
}

@error
model UnauthorizedError {
  code: "UNAUTHORIZED";
  message: string;
}

@error
model InternalServerError {
  code: "INTERNAL_SERVER_ERROR";
  message: string;
}

@error
model InternalServerErrorResponse {
  @statusCode statusCode: 500;
  @body error: InternalServerError;
}
